
; ================ MBR 模板 (512字节) ================
; 编译命令：nasm -f bin mbr.asm -o mbr.bin
; 写入磁盘：dd if=mbr.bin of=disk.img conv=notrunc

%include "init"         ;NASM汇编器格式:%

BITS 16                 ; 16位实模式
ORG MBR              ; BIOS 加载 MBR 的起始地址

start:
; -----------------------------------
    ; 初始化段寄存器与栈
    ; -----------------------------------
    xor ax, ax          ; AX = 0
    mov ds, ax          ; DS = 0 (数据段)
    mov es, ax          ; ES = 0 (附加段)
    mov ss, ax          ; SS = 0 (栈段)
    mov sp, MBR      ; SP = 0x7C00 (栈顶)

    ; -----------------------------------
    ; 清屏并设置视频模式
    ; -----------------------------------
    mov ax, 0x0003      ; 80x25 彩色文本模式
    int 0x10


    ; -----------------------------------
    ; 设置显存段（0xB800）
    ; -----------------------------------
    mov ax, 0xB800      ; 文本模式显存段
    mov es, ax          ; ES = 0xB800

    ; -----------------------------------
    ; 打印彩色字符串
    ; -----------------------------------
    mov si, msg         ; SI = 字符串地址
    mov di, (80 * 2) * 10  ; 屏幕第10行起始位置 (行*每行160字节)
    mov ah, 0x1E        ; 属性：蓝底黄字 (前4位背景，后4位前景)
    call print_string

    xchg bx, bx
    mov eax,LOADER_START_SECTOR	 ; 起始扇区lba地址; 扇区的起始是从0开始计数的
    mov ebx,LOADER_BASE_ADDR       ; 写入的地址
    mov ecx,LOAD_SECTOR_COUNT			 ; 待读入的扇区数
    call rd_disk_m_16		 ; 以下读取程序的起始部分（一个扇区）

    jmp LOADER_BASE_ADDR

;-------------------------------------------------------------------------------
;功能:读取硬盘n个扇区
rd_disk_m_16:
;-------------------------------------------------------------------------------
				       ; eax=LBA扇区号
				       ; ebx=将数据写入的内存地址
				       ; ecx=读入的扇区数
      mov esi,eax	  ;备份eax
      mov di,cx		  ;备份cx
;读写硬盘:
;第1步：设置要读取的扇区数
      mov dx,0x1f2
      mov al,cl
      out dx,al            ;读取的扇区数

      mov eax,esi	   ;恢复ax

;第2步：将LBA地址存入0x1f3 ~ 0x1f6

      ;LBA地址7~0位写入端口0x1f3
      mov dx,0x1f3
      out dx,al

      ;LBA地址15~8位写入端口0x1f4
      mov cl,8
      shr eax,cl
      mov dx,0x1f4
      out dx,al

      ;LBA地址23~16位写入端口0x1f5
      shr eax,cl
      mov dx,0x1f5
      out dx,al

      shr eax,cl
      and al,0x0f	   ;lba第24~27位
      or al,0xe0	   ; 设置7～4位为1110,表示lba模式
      mov dx,0x1f6
      out dx,al

;第3步：向0x1f7端口写入读命令，0x20
      mov dx,0x1f7
      mov al,0x20
      out dx,al

;第4步：检测硬盘状态
  .not_ready:
      ;同一端口，写时表示写入命令字，读时表示读入硬盘状态
      nop
      in al,dx
      and al,0x88	   ;第4位为1表示硬盘控制器已准备好数据传输，第7位为1表示硬盘忙
      cmp al,0x08
      jnz .not_ready	   ;若未准备好，继续等。

;第5步：从0x1f0端口读数据
      mov ax, di
      mov dx, 256
      mul dx
      mov cx, ax	   ; di为要读取的扇区数，一个扇区有512字节，每次读入一个字，
			   ; 共需di*512/2次，所以di*256
      mov dx, 0x1f0
  .go_on_read:
      in ax,dx
      mov [bx],ax
      add bx,2
      loop .go_on_read
      ret

; ================ 显存打印函数 ================
; 输入：SI=字符串地址, DI=显存偏移, AH=字符属性
print_string:
    pusha
.print_loop:
    lodsb               ; 加载字符 [SI] -> AL, SI++
    or al, al           ; 检测结束符 0
    jz .done
    stosw               ; 写入显存: [ES:DI] = AX (AL=字符, AH=属性), DI+2
    jmp .print_loop
.done:
    popa
    ret

; ================ 数据区 ================
msg db "I'm MBR", 0   ; 以0结尾的字符串

; ================ MBR 填充与签名 ================
times 510 - ($ - $$) db 0
dw 0xAA55

